#include <nice2d/string.h>
#include <nice2d/piece/faction.h>

class FactionData
{
public:
    std::wstring name;
    std::wstring desc;
    sf::Color color;
    std::list<sf::Color> alliances;
    std::shared_ptr<FactionController> controller;
};

Faction::Faction(const sf::Color &color, const std::wstring &name, const std::wstring &desc):
    data(new FactionData())
{
    data->color = color;
    data->name = name;
    data->desc = desc;
}

Faction::~Faction()
{
}

std::wstring Faction::getName() const
{
    return data->name;
}

sf::Color Faction::getColor() const
{
    return data->color;
}

void Faction::formAlliance(std::shared_ptr<Faction> other, bool alliance)
{
    if (!other)
        return;

    if (alliance) {
        data->alliances.push_back(other->getColor());
        other->data->alliances.push_back(getColor());
    } else {
        data->alliances.remove(other->getColor());
        other->data->alliances.remove(getColor());
    }
}

bool Faction::isAllied(const sf::Color &color)
{
    return std::find(data->alliances.begin(), data->alliances.end(), color) != data->alliances.end();
}

void Faction::setFactionController(std::shared_ptr<FactionController> controller)
{
    if(controller)
    {
        data->controller = controller;
        data->controller->setFactionColor(getColor());
    }
}

std::shared_ptr<FactionController> Faction::getFactionController() const
{
    return data->controller;
}

PTree Faction::serialize()
{
    PTree node;
    node.add("name", toString(data->name));
    node.add("desc", toString(data->desc));
    node.add_child("color",serializeObject(data->color));

    PTree alliances;
    std::for_each(data->alliances.begin(),
                  data->alliances.end(), [&alliances](const sf::Color & color) {
                      alliances.add_child("color",serializeObject(color));
                  });
    node.add_child("alliances", alliances);
    return node;
}

void Faction::deserialize(const PTree &root)
{
    auto name = root.get<std::string>(std::string("name"));
    data->name = toWString(name);

    auto desc = root.get<std::string>(std::string("desc"));
    data->desc = toWString(desc);

    auto color = root.get_child_optional("color");
    if (color.has_value())
        data->color = deserializeColor(color.value());

    auto alliances = root.get_child("alliances");
    std::for_each(alliances.begin(),alliances.end(),[&](const std::pair<std::string,PTree>& tree){data->alliances.push_back(deserializeColor(tree.second));});
}
